package com.jagochan.module.rbac.sys_user.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.jagochan.common.result.ResultUtils;
import com.jagochan.common.result.ResultVo;
import com.jagochan.module.rbac.common.Constants;
import com.jagochan.module.rbac.sys_menu.domain.SysMenu;
import com.jagochan.module.rbac.sys_menu.service.SysMenuService;
import com.jagochan.module.rbac.sys_role.domain.req.UpdatePasswordReq;
import com.jagochan.module.rbac.sys_user.domain.SysUser;
import com.jagochan.module.rbac.sys_user.domain.query.UserPageQuery;
import com.jagochan.module.rbac.sys_user.domain.req.LoginReq;
import com.jagochan.module.rbac.sys_user.domain.vo.LoginVo;
import com.jagochan.module.rbac.sys_user.domain.vo.UserInfoVo;
import com.jagochan.module.rbac.sys_user.service.SysUserService;
import com.jagochan.module.rbac.sys_user_role.service.SysUserRoleService;
import com.wf.captcha.SpecCaptcha;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@RequestMapping("/api/user")
@RestController
public class SysUserController {

    private final SysUserService sysUserService;
    private final SysUserRoleService sysUserRoleService;
    private final SysMenuService sysMenuService;
    private final PasswordEncoder passwordEncoder;

    private static final Cache<String, String> UUID_CAPTCHA_MAP = Caffeine.newBuilder()
            .maximumSize(900)
            .expireAfterWrite(Duration.ofMinutes(10))
            .build();

    @PostMapping
    public ResultVo<?> add(@RequestBody SysUser sysUser) {
        sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        sysUserService.saveUserWithRole(sysUser);
        return ResultUtils.success("新增用户成功!");
    }

    @PutMapping
    public ResultVo<?> edit(@RequestBody SysUser sysUser) {
        sysUserService.updateUserWithRole(sysUser);
        return ResultUtils.success("编辑用户成功!");
    }

    @DeleteMapping("{userId}")
    public ResultVo<?> delete(@PathVariable("userId") Long userId) {
        sysUserService.removeUserWithRole(userId);
        return ResultUtils.success("删除用户成功!");
    }

    @GetMapping("/page")
    public ResultVo<Page<SysUser>> getList(UserPageQuery query) {
        // 构造分页对象
        Page<SysUser> page = Page.of(query.getCurrentPage(), query.getPageSize());
        // 查询条件
        String nickName = query.getNickName();
        String phone = query.getPhone();
        page = sysUserService.lambdaQuery()
                .like(StringUtils.isNotEmpty(nickName), SysUser::getNickName, nickName)
                .like(StringUtils.isNotEmpty(phone), SysUser::getPhone, phone)
                .orderByDesc(SysUser::getUserId)
                .page(page);

        return ResultUtils.success("查询成功", page);
    }

    @GetMapping("/role-ids")
    public ResultVo<List<Long>> listRoleIds(Long userId) {
        return ResultUtils.success("查询成功", sysUserRoleService.listRoleIdsByUserId(userId));
    }

    @PostMapping("/reset-password")
    public ResultVo<?> resetPassword(@RequestBody SysUser sysUser) {
        if (sysUserService.resetPassword(sysUser.getUserId(), passwordEncoder)) {
            return ResultUtils.success("重置密码成功!");
        }
        return ResultUtils.error("重置密码失败!");
    }

    @GetMapping("/captcha")
    public ResultVo<Map<String, String>> captcha() {
        // 创建一个 SpecCaptcha 对象，设置验证码图片的宽度、高度和字符长度
        SpecCaptcha specCaptcha = new SpecCaptcha(200, 36, 5);

        String captcha = specCaptcha.text().toLowerCase();
        String uuid = UUID.randomUUID().toString();
        UUID_CAPTCHA_MAP.put(uuid, captcha);

        return ResultUtils.success("生成验证码成功", Map.of("uuid", uuid, "captchaImg", specCaptcha.toBase64()));
    }

    //登录x
    @PostMapping("/login")
    public ResultVo<?> login(@RequestBody LoginReq loginReq) {
        // 校验验证码
        String rightCaptcha = UUID_CAPTCHA_MAP.getIfPresent(loginReq.getUuid());
        if (StringUtils.isEmpty(rightCaptcha)) {
            return ResultUtils.error("验证码过期!");
        }
        if (!loginReq.getCaptcha().equals(rightCaptcha)) {
            return ResultUtils.error("验证码不正确!");
        }

        // 查询用户信息
        SysUser user = sysUserService.lambdaQuery().eq(SysUser::getUsername, loginReq.getUsername()).one();

        if (user == null) {
            return ResultUtils.error("账号不存在!");
        }

        if (!passwordEncoder.matches(loginReq.getPassword(), user.getPassword())) {
            return ResultUtils.error("密码错误!");
        }
        if (!user.isEnabled()) {
            return ResultUtils.error("账户已经被封禁，请联系系统管理员！");
        }
        StpUtil.login(user.getUserId(), "PC");

        return ResultUtils.success("登录成功", LoginVo.builder().userId(user.getUserId())
                .nickName(user.getNickName())
                .token(StpUtil.getTokenInfo().getTokenValue())
                .isAdmin(Objects.equals(Constants.IS_ADMIN, user.getIsAdmin()))
                .build());
    }

    @PostMapping("/update-password")
    public ResultVo<?> updatePassword(@RequestBody UpdatePasswordReq req) {
        SysUser user = sysUserService.lambdaQuery().eq(SysUser::getUserId, req.getUserId()).one();
        if (!passwordEncoder.matches(user.getPassword(), req.getOldPassword())) {
            return ResultUtils.error("原密码错误!");
        }
        user.setPassword(req.getNewPassword());
        if (sysUserService.updateById(user)) {
            return ResultUtils.success("密码修改成功");
        }
        return ResultUtils.error("密码修改失败");
    }

    @GetMapping("/get-user-info")
    public ResultVo<UserInfoVo> getUserInfo(String userId) {
        // 根据用户ID查询用户
        SysUser user = sysUserService.getById(userId);
        if (Objects.isNull(user)) return ResultUtils.error("用户不存在👉userId = " + userId, null);

        List<SysMenu> menuList;
        String isAdmin = user.getIsAdmin();
        if (StringUtils.isNotEmpty(isAdmin) && "1".equals(isAdmin)) { // 是超级管理员
            menuList = sysMenuService.list();
        } else { // 是普通用户
            menuList = sysMenuService.listMenuByUserId(userId);
        }
        UserInfoVo userInfoVo = new UserInfoVo();
        userInfoVo.setNickName(user.getNickName());
        userInfoVo.setUserId(user.getUserId());
        if (menuList == null || menuList.isEmpty()) {
            userInfoVo.setPermissionCodeList(Collections.emptyList());
        } else {
            userInfoVo.setPermissionCodeList(menuList.stream().filter(item -> item != null && StringUtils.isNotEmpty(item.getCode()))
                    .map(SysMenu::getCode)
                    .filter(StringUtils::isNotEmpty).collect(Collectors.toList()));
        }
        return ResultUtils.success("查询成功", userInfoVo);
    }

}
